#!/usr/bin/env python
# encoding: utf-8
"""
entity.py

Created by Morgan Quirk on 2007-08-09.
"""

import common
import pygame
import vector

class EntityManager:
    """Manages the entity list for efficient object creation / removal / updating"""
    def __init__(self):
        self.entity_list = []
        self.remove_list = []
        self.future_list = []
        
    def tick(self):
        """Finds all the ents that have to update in some way this tick, and performs the specified action"""
        if len(self.future_list)>0:
            for ent, action in self.future_list[0]:
                if action == "tick":
                    if ent in self.entity_list:
                        ent.on_tick(self)
                if action == "timeout":
                    if ent in self.entity_list:             
                        self.remove_entity(ent)
                else:
                    pass
                
        self.future_list = self.future_list[1:]

    def set_future(self, ent, action, t):
        """Internal function to set up an action to happen in a specific number of ticks"""
        if t<1:
            return
        if t>=len(self.future_list):
            for i in range(t-len(self.future_list)+1):
                self.future_list.append([])
                
        self.future_list[t].append((ent,action))
        
    def set_next_tick(self, ent, t):
        """Sets the tick time on an entity"""
        self.set_future(ent, "tick", t)
        
    def set_timeout(self, ent, t):
        """Sets the removal time on an entity"""
        self.set_future(ent, "timeout", t)
        
    def add_entity(self, ent):
        self.entity_list.append(ent)
        ent.on_create(self)
        
    def remove_entity(self, ent):
        ent.on_die(self)               
        self.remove_list.append(ent)
        
    def get_entities(self):
        return self.entity_list
        
    def __getitem__(self, ind):
        """So you can just say entity_manager[0] instead of entity_manager.entity_list[0]"""
        return self.entity_list[ind]
        
    def update(self):
        """Called at the end of every frame to remove everything that needs to be removed"""
        for ent in self.remove_list:
            try:
                self.entity_list.remove(ent)
            except:
                print "Failed to remove "+ent.entity_name+" from entity list!"
        self.remove_list = []
        
        
class Entity:
    entity_name = "Base Entity"
    base_image_name   = None
    base_col_rad      = 1
    global_friction   = 0.98
    
    def __init__(self, x, y, xv, yv, angle=0):
        self.x = int(x)
        self.y = int(y)
        self.xv = float(xv)
        self.yv = float(yv)
        self.angle = float(angle)
        
        self.forces=[]          
        self.collided=[]        #Prevents duplicate collisions in one update
        self.col_rad = self.base_col_rad
        
        self.timeout = -1       #Never
        
        self.image  = common.images[self.base_image_name]
        
        self.net_id = -1
        self.owner  = None
        
    def on_create(self, entity_manager):
        """Called when the entity is added to the entity list"""
        entity_manager.set_timeout(self, self.timeout)
        entity_manager.set_next_tick(self, 1)
        
    def on_die(self, entity_manager):
        """Called when the entity is about to be removed from the entitiy list"""
        pass
        
    def on_tick(self, entity_manager):
        """Called whenever the entity is scheduled to tick"""
        entity_manager.set_next_tick(self, 1)
    
    def get_image(self):
        """Called by draw, should return an image or None"""
        if self.image is not None:
            img=self.image.copy()
            if self.angle <> 0:
                img = pygame.transform.rotate(img, self.angle*180/3.14159)
            w = self.image.get_width()
            h = self.image.get_height()
            return (self.image, (self.x-w/2, self.y-h/2, self.x+w/2, self.y+h/2))
        else:
            return (None, (self.x, self.y, self.x, self.y))
            
            
class Entity_Test1(Entity):
    entity_name = "test1"
    base_image_name  = "circle"
    base_col_rad     = 12
                
class Entity_Test2(Entity):
    entity_name = "test1"
    base_image_name  = "circle2"
    base_col_rad     = 12